Skip to content

[All] Refactor nvte_get_fused_attn_backend with cudnn-frontend calls#2964

Open
cyanguwa wants to merge 40 commits into
NVIDIA:mainfrom
cyanguwa:fe_check_support
Open

[All] Refactor nvte_get_fused_attn_backend with cudnn-frontend calls#2964
cyanguwa wants to merge 40 commits into
NVIDIA:mainfrom
cyanguwa:fe_check_support

Conversation

@cyanguwa

@cyanguwa cyanguwa commented May 6, 2026

Copy link
Copy Markdown
Collaborator

Description

This PR replaces the hand-maintained backend selection logic in nvte_get_fused_attn_backend with cudnn-frontend's production-grade support checks.

  • It will build the same graph that runtime uses in execution, cache the graph if the build is successful, and provide a warmed-up cache for the next nvte_get_fused_attn_backend call.
  • It provides a cleaner dispatch logic, avoids accidental regressions, and helps TE to stay in sync with cudnn-frontend's support surface.
  • It also provides appropriate error messaging for when no backend is available, so users are notified and make config/architecture/cudnn version adjustments.

Type of change

  • Documentation change (change only to the documentation, either a fix or a new content)
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Infra/Build change
  • Code refactoring

Changes

See Description.

Checklist:

  • I have read and followed the contributing guidelines
  • The functionality is complete
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

cyanguwa and others added 4 commits May 5, 2026 18:55
Signed-off-by: Charlene Yang <8636796+cyanguwa@users.noreply.github.com>
Signed-off-by: Charlene Yang <8636796+cyanguwa@users.noreply.github.com>
Signed-off-by: Charlene Yang <8636796+cyanguwa@users.noreply.github.com>
@cyanguwa cyanguwa changed the title [Common] Refactor nvte_get_fused_attn_backend with cudnn-frontend calls [All] Refactor nvte_get_fused_attn_backend with cudnn-frontend calls May 8, 2026
Signed-off-by: Charlene Yang <8636796+cyanguwa@users.noreply.github.com>
@cyanguwa
cyanguwa marked this pull request as ready for review May 8, 2026 00:10
@greptile-apps

greptile-apps Bot commented May 8, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR replaces the hand-maintained boolean logic in nvte_get_fused_attn_backend with cudnn-frontend probe calls: it actually builds the same cuDNN graph that the runtime kernel will use (with null device pointers), caches it for future calls, and reports the real cuDNN error message when no backend is available.

  • A new FusedAttnConfig/FusedAttnFwdParams/FusedAttnBwdParams opaque-handle API is introduced in the public header, with v2 entry-points (nvte_get_fused_attn_backend_v2, nvte_fused_attn_fwd_v2, nvte_fused_attn_bwd_v2); PyTorch and JAX bindings are updated to use them.
  • The old nvte_get_fused_attn_backend is kept as a deprecated thin wrapper that constructs a FusedAttnConfig and delegates to the v2 path, but omits batch_size (stays 0), causing cuDNN to reject every probe graph and silently return NVTE_No_Backend for all BSHD/SBHD F16 configs.
  • graph_debug.h is included unconditionally and registers an atexit handler and atomic counters in every build; it is self-labeled "TEMPORARY DEBUG INSTRUMENTATION — REMOVE AFTER VERIFICATION".

Confidence Score: 2/5

Not safe to merge as-is: the deprecated wrapper regression silently returns NVTE_No_Backend for all BSHD/SBHD F16 configs, and temporary debug instrumentation with an atexit handler ships unconditionally.

The probe-based v2 approach is architecturally sound, but two defects block a clean merge: (1) the deprecated wrapper omits batch_size, causing cuDNN to reject every probe graph and silently breaking all existing callers; (2) graph_debug.h is self-labeled temporary yet registers an atexit handler and atomic counters in every build.

transformer_engine/common/fused_attn/fused_attn.cpp (deprecated wrapper batch_size=0 regression), transformer_engine/common/fused_attn/graph_debug.h (unconditional atexit handler in production builds)

Important Files Changed

Filename Overview
transformer_engine/common/fused_attn/fused_attn.cpp Core backend selection rewritten to use probe approach; deprecated wrapper silently breaks for all callers because batch_size=0 causes cuDNN to reject every probe graph
transformer_engine/common/fused_attn/config_and_params.h New FusedAttnConfig/FwdParams/BwdParams structs; defaults is_training=true, batch_size=0, o_format=NOT_SET expose silent misuse by the deprecated wrapper
transformer_engine/common/fused_attn/config_and_params.cpp New 1156-line file implementing the opaque config/params handle API; getter/setter switch statements appear complete and reachable
transformer_engine/common/fused_attn/graph_debug.h Self-described temporary debug instrumentation included unconditionally; atexit handler and atomic counters compiled into every build
transformer_engine/common/fused_attn/fused_attn_f16_arbitrary_seqlen.cu Refactored to accept FusedAttnConfig; causal mask now uses set_diagonal_band_right_bound(0) via the new diagonal-alignment API; is_supported_f16_fwd/bwd probe functions added
transformer_engine/common/fused_attn/fused_attn_fp8.cu Same FusedAttnConfig refactor as F16; new is_supported_fp8_fwd/bwd probe functions properly use std::to_string for error messages
transformer_engine/common/include/transformer_engine/fused_attn.h Adds 749 lines of new public API (NVTEFusedAttnConfig, v2 entry-points); old nvte_get_fused_attn_backend signature preserved but now delegates to the probe-based path
transformer_engine/pytorch/csrc/extensions/attention.cpp get_fused_attn_backend now takes py::object and populates FusedAttnConfigWrapper via chained setters; fwd/bwd rewritten to use FusedAttnFwdParamsWrapper/BwdParamsWrapper
transformer_engine/jax/cpp_extensions/attention.py FusedAttnHelper gains batch_size, bottom_right_diagonal, attn_scale, and bias-shape fields; get_fused_attn_backend now returns (backend, message) tuple

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant Caller as PyTorch/JAX/C++ Caller
    participant v2 as nvte_get_fused_attn_backend_v2
    participant pfwd as is_supported_f16_fwd
    participant pbwd as is_supported_f16_bwd
    participant ifwd as fused_attn_arbitrary_seqlen_fwd_impl
    participant ibwd as fused_attn_arbitrary_seqlen_bwd_impl
    participant cuDNN as cuDNN Graph Build

    Caller->>v2: NVTEFusedAttnConfig
    v2->>v2: early dtype/heads/seqlen checks
    v2->>pfwd: cfg + handle
    pfwd->>ifwd: "cfg with all device ptrs = nullptr"
    ifwd->>cuDNN: build fwd graph (batch, s_q, s_kv, h, d)
    alt graph builds OK
        cuDNN-->>ifwd: compiled graph
        ifwd-->>pfwd: workspace_size
        pfwd-->>v2: empty string (supported)
    else cuDNN rejects
        cuDNN-->>ifwd: exception
        pfwd-->>v2: error string
        v2-->>Caller: NVTE_No_Backend
    end
    alt is_training and not is_forward
        v2->>pbwd: cfg + handle
        pbwd->>ibwd: "cfg with all device ptrs = nullptr"
        ibwd->>cuDNN: build bwd graph
        cuDNN-->>ibwd: result or exception
        pbwd-->>v2: empty string or error string
    end
    v2-->>Caller: NVTE_F16_arbitrary_seqlen or NVTE_No_Backend
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant Caller as PyTorch/JAX/C++ Caller
    participant v2 as nvte_get_fused_attn_backend_v2
    participant pfwd as is_supported_f16_fwd
    participant pbwd as is_supported_f16_bwd
    participant ifwd as fused_attn_arbitrary_seqlen_fwd_impl
    participant ibwd as fused_attn_arbitrary_seqlen_bwd_impl
    participant cuDNN as cuDNN Graph Build

    Caller->>v2: NVTEFusedAttnConfig
    v2->>v2: early dtype/heads/seqlen checks
    v2->>pfwd: cfg + handle
    pfwd->>ifwd: "cfg with all device ptrs = nullptr"
    ifwd->>cuDNN: build fwd graph (batch, s_q, s_kv, h, d)
    alt graph builds OK
        cuDNN-->>ifwd: compiled graph
        ifwd-->>pfwd: workspace_size
        pfwd-->>v2: empty string (supported)
    else cuDNN rejects
        cuDNN-->>ifwd: exception
        pfwd-->>v2: error string
        v2-->>Caller: NVTE_No_Backend
    end
    alt is_training and not is_forward
        v2->>pbwd: cfg + handle
        pbwd->>ibwd: "cfg with all device ptrs = nullptr"
        ibwd->>cuDNN: build bwd graph
        cuDNN-->>ibwd: result or exception
        pbwd-->>v2: empty string or error string
    end
    v2-->>Caller: NVTE_F16_arbitrary_seqlen or NVTE_No_Backend
Loading

Reviews (20): Last reviewed commit: "[pre-commit.ci] auto fixes from pre-comm..." | Re-trigger Greptile

Comment thread transformer_engine/common/fused_attn/fused_attn_fp8.cu Outdated
Comment thread transformer_engine/common/fused_attn/fused_attn_fp8.cu Outdated
Comment thread transformer_engine/common/fused_attn/fused_attn.cpp Outdated
Comment thread transformer_engine/common/fused_attn/fused_attn.cpp
Comment thread transformer_engine/common/include/transformer_engine/fused_attn.h Outdated
cyanguwa and others added 2 commits May 7, 2026 17:22
Signed-off-by: Charlene Yang <8636796+cyanguwa@users.noreply.github.com>
Comment thread transformer_engine/common/fused_attn/fused_attn.cpp Outdated
cyanguwa and others added 3 commits May 7, 2026 18:30
Signed-off-by: Charlene Yang <8636796+cyanguwa@users.noreply.github.com>
Signed-off-by: Charlene Yang <8636796+cyanguwa@users.noreply.github.com>
@cyanguwa

cyanguwa commented May 8, 2026

Copy link
Copy Markdown
Collaborator Author

/te-ci L1

Comment thread transformer_engine/common/fused_attn/fused_attn_f16_arbitrary_seqlen.cu Outdated
Comment thread transformer_engine/common/fused_attn/fused_attn_f16_arbitrary_seqlen.cu Outdated
Comment thread transformer_engine/common/fused_attn/fused_attn.cpp
Signed-off-by: Charlene Yang <8636796+cyanguwa@users.noreply.github.com>
Comment thread transformer_engine/common/fused_attn/fused_attn_f16_arbitrary_seqlen.cu Outdated
Comment thread transformer_engine/common/fused_attn/fused_attn_f16_arbitrary_seqlen.cu Outdated
cyanguwa and others added 3 commits May 7, 2026 22:28
Signed-off-by: Charlene Yang <8636796+cyanguwa@users.noreply.github.com>
Signed-off-by: Charlene Yang <8636796+cyanguwa@users.noreply.github.com>
Comment thread transformer_engine/common/fused_attn/fused_attn.cpp Outdated
Comment thread transformer_engine/jax/cpp_extensions/attention.py
cyanguwa and others added 2 commits May 8, 2026 12:19
Signed-off-by: Charlene Yang <8636796+cyanguwa@users.noreply.github.com>
Comment thread transformer_engine/common/fused_attn/fused_attn.cpp Outdated
Comment thread transformer_engine/common/fused_attn/fused_attn.cpp Outdated
Signed-off-by: Charlene Yang <8636796+cyanguwa@users.noreply.github.com>
Comment thread transformer_engine/jax/flax/transformer.py
Comment thread transformer_engine/jax/csrc/extensions/pybind.cpp Outdated
@pggPL

pggPL commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

There is a limitation for torch.compile dynamic shapes here. If b and s are passed to black-box function affecting the program flow, I will need to force recompilation on every b or s change.
If we have args like s_greater_or_eq_512 and we check s >= 512 in python then no recompilation would be needed for every change of s. It may be more problematic for b.

I don't think this is a blocker for this PR, but we need to keep it in mind.

Comment thread transformer_engine/common/fused_attn/fused_attn.cpp Outdated
cyanguwa added 2 commits July 11, 2026 08:37
Signed-off-by: Charlene Yang <8636796+cyanguwa@users.noreply.github.com>
Signed-off-by: Charlene Yang <8636796+cyanguwa@users.noreply.github.com>
Comment thread transformer_engine/common/fused_attn/config_and_params.cpp Outdated
Signed-off-by: Charlene Yang <8636796+cyanguwa@users.noreply.github.com>
Comment thread transformer_engine/common/fused_attn/config_and_params.cpp Outdated
Comment thread transformer_engine/jax/cpp_extensions/attention.py
… fwd/bwd, thread bias shapes through in jax

Signed-off-by: Charlene Yang <8636796+cyanguwa@users.noreply.github.com>
cyanguwa and others added 2 commits July 14, 2026 14:34
Signed-off-by: Charlene Yang <8636796+cyanguwa@users.noreply.github.com>
Comment thread transformer_engine/common/fused_attn/config_and_params.cpp Outdated
Comment thread transformer_engine/common/fused_attn/config_and_params.cpp Outdated
cyanguwa added 2 commits July 15, 2026 07:17
…cache_key, fix Jax bias

Signed-off-by: Charlene Yang <8636796+cyanguwa@users.noreply.github.com>
…raph_debug, fix bias shape handling

Signed-off-by: Charlene Yang <8636796+cyanguwa@users.noreply.github.com>
Comment thread transformer_engine/common/fused_attn/fused_attn.cpp
Signed-off-by: Charlene Yang <8636796+cyanguwa@users.noreply.github.com>
Comment on lines +1 to +23
/*************************************************************************
* Copyright (c) 2022-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*
* See LICENSE for license information.
************************************************************************/

// ============================================================================
// [GRAPH-DEBUG] TEMPORARY DEBUG INSTRUMENTATION -- REMOVE AFTER VERIFICATION.
//
// Counts fused-attention cuDNN graph *builds* (cache misses that construct a new
// graph) vs. *executions* (real forward/backward runs, excluding workspace-sizing
// probes) to detect redundant graph construction.
//
// Enable at runtime with: export NVTE_FUSED_ATTN_GRAPH_DEBUG=1
// A running "BUILD" line is printed whenever a new graph is constructed, and a
// "SUMMARY" line with final totals is printed at process exit.
//
// To remove all of this instrumentation later:
// 1. Delete this file (graph_debug.h).
// 2. Remove every line tagged with the "[GRAPH-DEBUG]" marker in:
// - fused_attn_fp8.cu
// - fused_attn_f16_arbitrary_seqlen.cu
// ============================================================================

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Temporary debug instrumentation shipped in production build

This file is explicitly labeled "TEMPORARY DEBUG INSTRUMENTATION -- REMOVE AFTER VERIFICATION" in its own header comment, yet it is included in this PR. The atexit handler and atomic counters are compiled into every build unconditionally; only the runtime output is gated behind NVTE_FUSED_ATTN_GRAPH_DEBUG. This should be removed before merge or tracked with a follow-up issue — otherwise the instrumentation accumulates permanently in the library.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Signed-off-by: Charlene Yang <8636796+cyanguwa@users.noreply.github.com>
Comment on lines +351 to +353
transformer_engine::FusedAttnConfig cfg{};
cfg.qkv_layout = qkv_layout;
cfg.bias_type = bias_type;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Deprecated wrapper leaves batch_size=0, breaking all BSHD/SBHD probes

FusedAttnConfig cfg{} zero-initialises batch_size. The old API signature had no such parameter, so the wrapper never sets it. is_supported_f16_fwd then calls derive() (which bucketed_batch_size inherits from zero) and calls into fused_attn_arbitrary_seqlen_fwd_impl with b = 0. cuDNN rejects a graph whose batch tensor has size 0, throwing an exception. The catch block returns a non-empty error string, and nvte_get_fused_attn_backend_v2 returns NVTE_No_Backend for every BSHD/SBHD F16 configuration — a silent regression for every existing caller of the deprecated entry-point. A safe fallback is to seed cfg.batch_size = 1 since the probe only needs a structurally-valid (non-zero) dimension to succeed.

Suggested change
transformer_engine::FusedAttnConfig cfg{};
cfg.qkv_layout = qkv_layout;
cfg.bias_type = bias_type;
transformer_engine::FusedAttnConfig cfg{};
cfg.batch_size = 1; // probe needs a non-zero batch; old API had no batch_size parameter
cfg.qkv_layout = qkv_layout;
cfg.bias_type = bias_type;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants